﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BeanboxSoftware.BeanMap;

namespace BeanboxSoftware.BeanMapTest
{
  [TestClass]
  public class MapDictionaryTupleBaseTest
  {
    [TestMethod]
    public void TryGetValueTest()
    {
      var map = new Map<int, string>();

      map[1] = "one";
      map.DefaultValue = "not found";

      var dict = (IDictionary<int, string>)map;

      string result;

      Assert.IsFalse(dict.TryGetValue(0, out result), "try get 0");
      Assert.IsNull(result, "result string 0");

      Assert.IsTrue(dict.TryGetValue(1, out result), "try get 1");
      Assert.AreEqual("one", result, "result string 1");

      map.DefaultGeneration = _ => "default";

      Assert.IsFalse(dict.TryGetValue(0, out result), "try get 0 default gen");
      Assert.IsNull(result, "result string 0 default gen");
    }

    [TestMethod]
    public void AddTest()
    {
      var map = new Map<int, string>();
      var dict = (IDictionary<int, string>)map;

      map[1] = "one";

      TestUtils.AssertExceptionThrown<ArgumentException>(() => { map.Add(1, "void"); });
      Assert.AreEqual("one", map[1]);

      TestUtils.AssertExceptionThrown<ArgumentException>(() => { dict.Add(1, "void"); });
      Assert.AreEqual("one", map[1]);
    }

    [TestMethod]
    public void KVEnumerableTest()
    {
      var map = new Map<int, string>();

      map[1] = "one";
      map[2] = "two";

      var dict = (IDictionary<int, string>)map;
      var gd = (System.Collections.IEnumerable)map;

      var em = dict.GetEnumerator();
      var gem = gd.GetEnumerator();

      int i = 1;
      while (true)
      {
        int m = 0;
        m += em.MoveNext() ? 1 : 0;
        m += gem.MoveNext() ? 1 : 0;

        if (m != 0)
        {
          Assert.AreEqual(2, m);
          break;
        }

        Assert.AreEqual(em.Current.Value, map[i]);
        Assert.AreEqual(((KeyValuePair<object[], object>)gem.Current).Value, map[i]);

        i++;
      }
    }

    [TestMethod]
    public void KVRemoveTest()
    {
      var map = new Map<int, string>();
      map[1] = "one";

      Assert.IsTrue(map.ContainsKey(1));
      Assert.IsFalse(map.ContainsKey(2));

      var dic = (IDictionary<int, string>)map;
      var kvp = new KeyValuePair<int, string>(map.KeyValues.First().Key, map.KeyValues.First().Value);

      Assert.IsTrue(dic.Remove(kvp));
      Assert.IsFalse(dic.Remove(kvp));
    }

    [TestMethod]
    public void KVAddKeyValuePairTest()
    {
      var map = new Map<int, string>();
      var dict = (IDictionary<int, string>)map;

      dict.Add(new KeyValuePair<int, string>(1, "one"));

      Assert.AreEqual(1, map.Count);
      Assert.AreEqual("one", map[1]);

      TestUtils.AssertExceptionThrown<ArgumentException>(() => { dict.Add(new KeyValuePair<int, string>(1, "two")); });
      TestUtils.AssertExceptionThrown<ArgumentException>(() => { dict.Add(new KeyValuePair<int, string>(1, "one")); });
    }

    [TestMethod]
    public void KVContainsTest()
    {
      var map = new Map<int, string>();
      map[1] = "one";

      var dic = (IDictionary<int, string>)map;

      Assert.IsTrue(map.Contains(new KeyValuePair<int, string>(1, "one")));

      Assert.IsTrue(dic.Contains(new KeyValuePair<int, string>(1, "one")));
      Assert.IsFalse(dic.Contains(new KeyValuePair<int, string>(1, "two")));
      Assert.IsFalse(dic.Contains(new KeyValuePair<int, string>(2, "one")));
      Assert.IsFalse(dic.Contains(new KeyValuePair<int, string>(2, "two")));
    }
  }
}
